package cate.game.role.res.call;

import cate.common.table.call.row.CallBaseRow;
import cate.game.res.CostSelect;
import cate.game.role.Role;
import cate.game.role.RoleDependent;
import cate.game.role.res.call.advance.CallAdvanceCallPO;
import cate.game.role.res.call.base.CallProcessData;
import cate.game.role.res.call.base.ICallExe;
import cate.game.role.res.call.base.ICallHandler;
import cate.game.role.res.call.friend.FriendCallPO;
import cate.game.role.res.call.msg.CallDataResp;
import cate.game.role.res.call.nature.CallNatureCallPO;
import cate.game.role.res.call.normal.CallNormalCallPO;
import cate.game.role.res.call.scorecall.CallScoreCallPO;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import org.springframework.data.annotation.Transient;

import java.util.HashMap;
import java.util.Map;

@NoteClass("召唤总数据")
public class CallPO extends RoleDependent {

  @JsonIgnore
  @NoteField(value = "公用")
  public CallTool tool;

  @JsonIgnore
  @NoteField(value = "各个召唤入口", detail = "Map<召唤模式,召唤模式对应的调用接口>")
  @Transient
  public transient Map<Byte, ICallExe> callMap;

  @NoteField(value = "普通召唤")
  public CallNormalCallPO normal;

  @NoteField(value = "友情召唤")
  public FriendCallPO friend;

  @NoteField(value = "高级召唤")
  public CallAdvanceCallPO advance;

  @NoteField(value = "积分召唤")
  public CallScoreCallPO score;

  @NoteField(value = "食神召唤")
  public CallNatureCallPO nature;

  @NoteField(value = "自动分解是否开启")
  public boolean autoResolve;

  public void setAutoResolve(boolean autoResolve) {
    this.autoResolve = autoResolve;
    noticeCallDataUpdate();
  }

  public void noticeCallDataUpdate() {
    role.sendNow(new CallDataResp(this));
  }

  @Override
  public void initialize(Role role) {
    super.initialize(role);
    if (tool == null) {
      tool = new CallTool();
    }
    if (callMap == null) {
      callMap = new HashMap<>();
    }
    if (normal == null) {
      normal = new CallNormalCallPO();
    }
    normal.initialize(role, tool);
    if (friend == null) {
      friend = new FriendCallPO();
    }
    friend.initialize(role, tool);
    if (advance == null) {
      advance = new CallAdvanceCallPO();
    }
    advance.initialize(role, tool);
    if (score == null) {
      score = new CallScoreCallPO();
    }
    score.initialize(role, tool);
    if (nature == null) {
      nature = new CallNatureCallPO();
    }
    nature.initialize(role, tool);
  }

  @Override
  public void onEnter() {
    super.onEnter();
    repair();
    this.nature.onEnter();
  }

  private void repair() {
    if (callMap.size() > 0) {
      if ((!callMap.containsValue(normal))
              || (!callMap.containsValue(nature))
              || (!callMap.containsValue(friend))
              || (!callMap.containsValue(advance))
              || (!callMap.containsValue(score))) {
        logger.info("英雄置换" + role.getBase().name + "重置了map");
        this.initialize(role);
      }
    }
  }

  public void call(int type, CostSelect cs) {
    //构造processData
    CallProcessData data = new CallProcessData();
    data.cs = cs;
    CallBaseRow base = getBaseRow(role, type);
    data.setBase(base);
    data.setMaxTime(base.callTimes);

    ICallExe call = getCallPO(base.callMode);
    ICallHandler handler = CallManager.getHandler(type);
    if (!handler.callPreCheck(role, data, call.onGotPO(role))) {
      return;
    }
    call.callExe(role, data, CallManager.getHandler(type), call.onGotPO(role));
    if (data.result.size() < data.getMaxTime()) {
      return;
    }
    call.modifyByMods(role, data, CallManager.getHandler(type), call.onGotPO(role));
    call.handleResult(role, data, CallManager.getHandler(type), call.onGotPO(role));
  }

  public ICallExe getCallPO(byte type) {
    return callMap.get(type);
  }

  public void register(byte type, ICallExe po) {
    callMap.put(type, po);
  }

  @JsonIgnore
  public CallBaseRow getBaseRow(Role role, int type) {
    CallBaseRow row = role.getGame().table.call.base.get(type);
    if (row == null) {
      role.getGame().notice.message(role, "错误的召唤类型");
      return null;
    }
    return row;
  }

  public void release(String heroUid) {
    nature.release(heroUid);
  }

  public void refresh() {
    /* 更新召唤数据，比如 召唤次数的刷新 */
    long now = System.currentTimeMillis();
    if (callMap == null) {
      return;
    }
    for (CallBaseRow tpl : role.getGame().table.call.base.list) {
      if (tpl.refreshInterval == 0) {
        continue;
      }
      ICallExe call = callMap.get(tpl.callMode);
      if (call == null) {
        return;
      }
      CallBasePO status = callMap.get(tpl.callMode).onGotPO(role);
      if (status == null) {
        continue;
      }
      if (now - status.baseData.lastFreeTime >= tpl.refreshInterval * 1000
              && status.baseData.freeTimes < tpl.freeMax) {
        status.baseData.freeTimes++;
        status.baseData.lastFreeTime = now;
      }
    }
    role.sendNow(new CallDataResp(this));
  }

  @Override
  public void onDaySpan(boolean silence) {
    super.onDaySpan(silence);
    this.nature.onDaySpan(silence);
    noticeCallDataUpdate();
  }

  public void clear() {
    callMap.clear();
    normal = null;
    advance = null;
    friend = null;
    score = null;
    nature = null;
  }

}
